﻿using RazorEngine;
using System;
using System.Diagnostics;
using System.IO;
using TestMonkey.Models;

namespace TestMonkey
{
	public abstract class TemplateProcessor
	{

		protected TemplateProcessor()
		{
			CreateMode = CreationMode.Overwrite;
		}

		internal void ProcessTemplate(ModelRoot model)
		{

			if (!ShouldRun(model))
				return;

			var template = LoadTemplate(model.Setup, GetType().Name);

			string text;
			try
			{
				text = Razor.Parse(template, model, GetType().FullName);
			}
			catch (RazorEngine.Templating.TemplateCompilationException ex)
			{
				if (model.Setup.SkipTemplateOnError)
				{
					Console.WriteLine(String.Format("Error processing template {0} for class {1}\r\n{2}", GetType().Name, model.Type.Name, ex.Message));
					Debug.WriteLine(String.Format("Error processing template {0} for class {1}\r\n{2}", GetType().Name, model.Type.Name, ex.Message));
					return;
				}
				else
					throw;

			}

			WriteFile(model, model.Setup, model.Type, GetType().Name, text);
		}

		static string LoadTemplate(Setup setup, string templateName)
		{
			var rootFolder = setup.TemplateLocation;
			var fullPath = Path.Combine(rootFolder, "Templates", templateName + ".cshtml");
			if (!File.Exists(fullPath))
				throw new ArgumentException("Cannot find template named " + templateName);

			var template = File.ReadAllText(fullPath);
			return template;
		}

		protected abstract bool ShouldRun(ModelRoot model);

		public CreationMode CreateMode { get; set; }

		void WriteFile(ModelRoot model, Setup setup, Type type, string part, string contents)
		{
			if (model == null)
				throw new ArgumentNullException("model", "model is null.");
			if (setup == null)
				throw new ArgumentNullException("setup", "setup is null.");
			if (type == null)
				throw new ArgumentNullException("type", "type is null.");
			if (part == null)
				throw new ArgumentNullException("part", "part is null.");
			if (contents == null)
				throw new ArgumentNullException("contents", "contents is null.");

			var file = setup.GetTargetFile(model, type, part);
			if (file.Exists)
			{
				if (CreateMode == CreationMode.Overwrite)
				{
					if (File.ReadAllText(file.FullName) != contents)
					{
						Console.WriteLine("\tUpdating " + file.FullName.Substring(setup.TargetFolder.Length + 1));
						File.WriteAllText(file.FullName, contents);
					}
				}
			}
			else
			{
				file.Directory.Create();
				File.WriteAllText(file.FullName, contents);
				Console.WriteLine("\tCreating " + file.FullName.Substring(setup.TargetFolder.Length + 1));
			}
		}

	}
}
